package cn.wolfcode.shop.cloud.service.impl;

import cn.wolfcode.shop.cloud.common.BusinessException;
import cn.wolfcode.shop.cloud.common.Result;
import cn.wolfcode.shop.cloud.domain.Good;
import cn.wolfcode.shop.cloud.domain.SeckillGood;
import cn.wolfcode.shop.cloud.feign.GoodsFeignApi;
import cn.wolfcode.shop.cloud.mapper.SeckillGoodMapper;
import cn.wolfcode.shop.cloud.redis.RedisService;
import cn.wolfcode.shop.cloud.service.ISeckillGoodService;
import cn.wolfcode.shop.cloud.util.SeckillCodeMsg;
import cn.wolfcode.shop.cloud.util.SeckillKeyPrefix;
import cn.wolfcode.shop.cloud.vo.SeckillGoodVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class SeckillGoodServiceImpl implements ISeckillGoodService {

    @Autowired
    private SeckillGoodMapper seckillGoodMapper;
    @Autowired
    private GoodsFeignApi goodsFeignApi;
    @Autowired
    private RedisService redisService;

    @Override
    public List<SeckillGoodVO> query() {
        // 1 上秒杀商品列表中查询出List<SeckillGood> list
        List<SeckillGood> seckillGoods = seckillGoodMapper.querySeckillGoods();
        return commonQuery(seckillGoods);
    }

    @Override
    public SeckillGoodVO getSeckillGoodById(Long seckillId) {
        SeckillGood seckillGood = seckillGoodMapper.findById(seckillId);
        ArrayList<SeckillGood> seckillGoods = new ArrayList<>();
        seckillGoods.add(seckillGood);
        return commonQuery(seckillGoods).get(0);
    }

    @Override
    public int decrCount(Long seckillId) {
        return seckillGoodMapper.decrCount(seckillId);
    }

    @Override
    public SeckillGoodVO findByCache(Long seckillId) {
        SeckillGoodVO goodVO = redisService.hget(SeckillKeyPrefix.SECKILL_GOOD_HASH, "", seckillId + "", SeckillGoodVO.class);
        //redis中的数据
        Integer count = redisService.get(SeckillKeyPrefix.SECKILL_GOOD_STOCK, seckillId + "", Integer.class);
        if (count < 0) {
            count = 0;
        }
        goodVO.setStockCount(count);
        return goodVO;
    }

    @Override
    public List<SeckillGoodVO> queryByCache() {
        Map<String, SeckillGoodVO> goodVOMap = redisService.hgetAll(SeckillKeyPrefix.SECKILL_GOOD_HASH, "", SeckillGoodVO.class);
        List<SeckillGoodVO> vos = new ArrayList<>();
        for (Map.Entry<String, SeckillGoodVO> voEntry : goodVOMap.entrySet()) {
            vos.add(voEntry.getValue());
        }
        for (SeckillGoodVO vo : vos) {
            Integer count = redisService.get(SeckillKeyPrefix.SECKILL_GOOD_STOCK, vo.getId() + "", Integer.class);
            if (count < 0) {
                count = 0;
            }
            vo.setStockCount(count);
        }
        return vos;
    }

    @Override
    public void incrCount(Long goodId) {
        seckillGoodMapper.incrCount(goodId);
    }

    @Override
    public void syncPreStockCount(Long goodId) {
        //先从数据库查询出真实库存
        SeckillGoodVO seckillGoodVO = getSeckillGoodById(goodId);
        //重新放到redis中
        redisService.set(SeckillKeyPrefix.SECKILL_GOOD_STOCK, ""+goodId, seckillGoodVO.getStockCount());
    }

    private List<SeckillGoodVO> commonQuery(List<SeckillGood> seckillGoods) {
        // 2 把商品的id放到一个Set集合中
        Set<Long> goodIds = new HashSet<>();
        for (SeckillGood seckillGood : seckillGoods) {
            goodIds.add(seckillGood.getGoodId());
        }
        ArrayList<Long> list = new ArrayList<>(goodIds);
        // 3 远程调用商品服务拿到商品的数据
        Result<List<Good>> listResult = goodsFeignApi.queryGoods(list);
        if (listResult == null || listResult.getCode() != 200) {
            throw new BusinessException(SeckillCodeMsg.GOODS_ERROR);
        }
        Map<Long, Good> data = new HashMap<>();
        for (Good good : listResult.getData()) {
            data.put(good.getId(), good);
        }
        // 4 在内存中进行聚合操作
        List<SeckillGoodVO> seckillGoodVOs = new ArrayList<>();
        for (SeckillGood seckillGood : seckillGoods) {
            SeckillGoodVO seckillGoodVO = new SeckillGoodVO();
            Good good = data.get(seckillGood.getGoodId());
            seckillGoodVO.setGoodDetail(good.getGoodDetail());
            seckillGoodVO.setGoodImg(good.getGoodImg());
            seckillGoodVO.setGoodName(good.getGoodName());
            seckillGoodVO.setGoodPrice(good.getGoodPrice());
            seckillGoodVO.setGoodStock(good.getGoodStock());
            seckillGoodVO.setGoodTitle(good.getGoodTitle());
            seckillGoodVO.setGoodId(good.getId());
            seckillGoodVO.setSeckillPrice(seckillGood.getSeckillPrice());
            seckillGoodVO.setStartDate(seckillGood.getStartDate());
            seckillGoodVO.setEndDate(seckillGood.getEndDate());
            seckillGoodVO.setStockCount(seckillGood.getStockCount());
            seckillGoodVO.setId(seckillGood.getId());
            seckillGoodVOs.add(seckillGoodVO);
        }
        return seckillGoodVOs;
    }
}
